package com.yc.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Junit {
    /**
     * 扩展实现:
     *  1. 对测试结果统计: 正确, 异常, 错误(扩展:断言)
     *  2. 测试方法的顺序执行, order 值越小越早执行
     * @param args
     */
    public static void main(String[] args) {
        runTest(new MyTest());
    }

    public static void runTest(Object test){
        Class<?> aClass = test.getClass();
        Method[] methods = aClass.getDeclaredMethods();

        // before
        for (Method method : methods) {
            Before before = method.getAnnotation(Before.class);
            if(before!=null){
                try {
                    method.invoke(test);
                } catch (IllegalAccessException e) {
                    // Junit 要求所有的测试相关方法必须是 public
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    // 被测试方法异常
                    e.printStackTrace();
                }
            }
        }

        // test
        for (Method method : methods) {
            Test testAnno = method.getAnnotation(Test.class);
            if(testAnno!=null){
                try {
                    method.invoke(test);
                } catch (IllegalAccessException e) {
                    // Junit 要求所有的测试相关方法必须是 public
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    // 被测试方法异常
                    e.printStackTrace();
                }
            }
        }

        // after
        for (Method method : methods) {
            After after = method.getAnnotation(After.class);
            if(after!=null){
                try {
                    method.invoke(test);
                } catch (IllegalAccessException e) {
                    // Junit 要求所有的测试相关方法必须是 public
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    // 被测试方法异常
                    e.printStackTrace();
                }
            }
        }
    }

}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Test{
    int order();
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Before{

}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface After{

}

class MyTest{

    @Before
    public void before(){
        System.out.println("before");
    }

    @After
    public void after(){
        System.out.println("after");
    }

    @Test(order=1)
    public void test1(){
        System.out.println("test1");
    }

    @Test(order = 2)
    public void test2(){
        System.out.println("test2");
        int i = 1/0;
    }

    public void test3(){
        System.out.println("test3");
    }
}